package com.example.act6.assist;

import cn.hutool.core.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.ActivitiEventListener;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class GlobalEventListener implements ActivitiEventListener, ApplicationListener<ContextRefreshedEvent> {

    private final Map<ActivitiEventType, ActivitiEventHandler<ActivitiEvent>> globalEventHandlerMap = new ConcurrentHashMap<>();

    @Override
    public void onEvent(ActivitiEvent event) {
        ActivitiEventHandler<ActivitiEvent> handler = this.globalEventHandlerMap.get(event.getType());
        if (handler != null) {
            if (log.isInfoEnabled()) {
                log.info("开始调用[" + handler.getClass().getSimpleName() + "]事件处理器");
            }
            try {
                handler.handle(event);
                if (log.isInfoEnabled()) {
                    log.info("开始调用[" + handler.getClass().getSimpleName() + "]事件处理器");
                }
            } catch (Exception e) {
                throw new RuntimeException("Activiti事件执行器执行失败，执行器: " + handler.getClass().getName(), e);
            }
            if (log.isInfoEnabled()) {
                log.info("完成调用[" + handler.getClass().getSimpleName() + "]事件处理器");
            }
        }
    }

    @Override
    public boolean isFailOnException() {
        return true;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        event.getApplicationContext().getBeansOfType(ActivitiEventHandler.class).values().forEach(eventHandler -> {
            Handler handlerAnnotation = AnnotatedElementUtils.findMergedAnnotation(eventHandler.getClass(), Handler.class);
            Assert.notNull(handlerAnnotation, eventHandler.getClass().getName() + " 未设置@Handler");
            if (log.isInfoEnabled()) {
                log.info(eventHandler.getClass().getName() + " load");
            }
            this.globalEventHandlerMap.put(handlerAnnotation.eventType(), eventHandler);
        });
    }
}
